﻿#include "FITKNastranAdaptorCase.h"
#include "FITKNastranAdaptorModel.h"
#include "FITKNastranAdaptorMaterial.h"
#include "FITKNastranAdaptorProperty.h"

#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKSectionAssign.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractSection.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterial.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSectionBeam.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSectionShellHomogeneous.h"
#include "FITK_Kernel/FITKAdaptor/FITKIOAdaptorFactory.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"

#include <QDebug>

namespace Nastran
{
    // Constructor for FITKNastranAdaptorCase, setting up adaptors for material, section, and part
    FITKNastranAdaptorCase::FITKNastranAdaptorCase()
    {
    }

    FITKNastranAdaptorCase::~FITKNastranAdaptorCase()
    {
        for (QHash<QString, FITKNastranAbstractAdaptor*>::iterator iter = _adaptorIO.begin(); iter != _adaptorIO.end(); ++iter)
        {
            if (iter.value()) delete iter.value();
        }
    }

    void FITKNastranAdaptorCase::setCaseData(AbaqusData::FITKDataCase *caseData)
    {
        _caseData = caseData;
    }

    void FITKNastranAdaptorCase::setPartData(AbaqusData::FITKAbaqusPart *partData)
    {
        _partData = partData;
    }

    bool FITKNastranAdaptorCase::adaptR()
    {
        if (nullptr == _reader || nullptr == _caseData)
        {
            return false;
        }
        bool readOK = true;
        while (!_reader->atEnd())
        {
            //读取行数据
            QString line = _reader->readLine().toUpper();
            //发送读取进度
            _reader->sendCurrentPercent();
            bool OK = false;
            //读取节点
            if (line.startsWith("GRID"))
            {
                OK = this->readModelNode();
            }
            //读取单元
            else if (line.startsWith("CTRIA3") || line.startsWith("CQUAD4") || line.startsWith("CHEXA") || line.startsWith("CTETRA") || line.startsWith("CBAR"))
            {
                OK = this->readModelElement();
            }
            //读取材料
            else if (line.startsWith("MAT1"))
            {
                OK = this->readMaterial();
            }
            //读取属性
            else if (line.startsWith("PSHELL") || line.startsWith("PBAR"))
            {
                OK = this->readProperty();
            }

            //读取关键字正确判断
            if (OK)
            {
                //调用解析函数后要执行回退
                _reader->backLine();
            }

            //readOK &= OK;
        }
        
        return readOK;
    }

    bool FITKNastranAdaptorCase::adaptW()
    {
        if (!_writer) return false;
        bool writeOK = true;
        QTextStream* stream = _writer->getStream();
        *stream << "CEND" << endl;
        *stream << "BEGIN BULK" << endl;
        writeOK &= this->writeModelNode();
        writeOK &= this->writeModelElement();
        writeOK &= this->writeMaterial();
        writeOK &= this->writeProperty();
        *stream << "ENDDATA" << endl;
        return true;
    }

    bool FITKNastranAdaptorCase::readModelNode()
    {
        if (!_reader) return false;
        //获取节点数据行
        QString line = _reader->previousLine();
        //create ModelNodel adaptor
        if (!_adaptorIO.contains("ModelNode"))
        {
            _adaptorIO.insert("ModelNode", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorModelNode>("BDF", "NastranModelNode"));
        }
        Nastran::FITKNastranAdaptorModelNode* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorModelNode*>(_adaptorIO.value("ModelNode"));
        //check if the ModelNodel adaptor is available
        if (adaptor == nullptr) return false;
        //Set necessary components for the ModelNodel adaptor
        adaptor->setReader(_reader);
        adaptor->setDataObject(_partData);
        bool result = adaptor->adaptR();
        if (!result)
        {
            _reader->consoleMessage(3, QString("read Node err ! %1").arg(line));
            return false;
        }
        //Return the result of the adaptation process
        return result;
    }

    bool FITKNastranAdaptorCase::writeModelNode()
    {
        if (!_writer) return false;
        //create ModelNodel adaptor
        if (!_adaptorIO.contains("ModelNode"))
        {
            _adaptorIO.insert("ModelNode", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorModelNode>("BDF", "NastranModelNode"));
        }
        Nastran::FITKNastranAdaptorModelNode* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorModelNode*>(_adaptorIO.value("ModelNode"));
        //check if the ModelNodel adaptor is available
        if (adaptor == nullptr) return false;
        //Set necessary components for the ModelNodel adaptor
        adaptor->setWriter(_writer);
        adaptor->setDataObject(_partData);
        bool result = adaptor->adaptW();
        if (!result)
        {
            _writer->consoleMessage(3, QString("write Node err !"));
            return false;
        }
        return result;
    }

    bool FITKNastranAdaptorCase::readModelElement()
    {
        if (!_reader) return false;
        //获取单元数据行
        QString line = _reader->previousLine();
        //create ModelElement adaptor
        if (!_adaptorIO.contains("ModelElement"))
        {
            _adaptorIO.insert("ModelElement", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorModelElement>("BDF", "NastranModelElement"));
        }
        Nastran::FITKNastranAdaptorModelElement* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorModelElement*>(_adaptorIO.value("ModelElement"));
        //check if the ModelElement adaptor is available
        if (adaptor == nullptr) return false;
        //Set necessary components for the ModelElement adaptor
        adaptor->setReader(_reader);
        adaptor->setDataObject(_partData);
        bool result = adaptor->adaptR();
        if (!result)
        {
            _reader->consoleMessage(3, QString("read Element err ! %1").arg(line));
            return false;
        }
        //Return the result of the adaptation process
        return result;
    }

    bool FITKNastranAdaptorCase::writeModelElement()
    {
        if (!_writer) return false;
        //create ModelElement adaptor
        if (!_adaptorIO.contains("ModelElement"))
        {
            _adaptorIO.insert("ModelElement", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorModelElement>("BDF", "NastranModelElement"));
        }
        Nastran::FITKNastranAdaptorModelElement* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorModelElement*>(_adaptorIO.value("ModelElement"));
        //check if the ModelElement adaptor is available
        if (adaptor == nullptr) return false;
        //Set necessary components for the ModelElement adaptor
        adaptor->setWriter(_writer);
        adaptor->setDataObject(_partData);
        bool result = adaptor->adaptW();
        if (!result)
        {
            _writer->consoleMessage(3, QString("write Element err !"));
            return false;
        }
        return result;
    }

    bool FITKNastranAdaptorCase::readMaterial()
    {
        if (!_reader || !_caseData) return false;
        //获取管理器
        Interface::FITKMaterialManager * materialMgr = _caseData->getMaterialManager();
        if (!materialMgr) return false;
        //获取材料数据行
        QString line = _reader->previousLine();
        //create Material adaptor
        if (!_adaptorIO.contains("Material"))
        {
            _adaptorIO.insert("Material", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorMaterial>("BDF", "NastranMaterial"));
        }
        //创建材料对象
        Interface::FITKAbaMaterial* materialPtr = new Interface::FITKAbaMaterial;
        Nastran::FITKNastranAdaptorMaterial* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorMaterial*>(_adaptorIO.value("Material"));
        //check if the Material adaptor is available
        if (adaptor == nullptr) return false;
        //Set necessary components for the Material adaptor
        adaptor->setReader(_reader);
        adaptor->setDataObject(materialPtr);
        bool result = adaptor->adaptR();
        if (!result)
        {
            _reader->consoleMessage(3, QString("read Material err ! %1").arg(line));
            delete materialPtr;
            return false;
        }
        //重新设置名称-防止名称重复
        materialPtr->setDataObjectName(materialMgr->checkName(materialPtr->getDataObjectName()));
        //添加数据到管理器
        materialMgr->appendDataObj(materialPtr);
        //Return the result of the adaptation process
        return result;
    }

    bool FITKNastranAdaptorCase::writeMaterial()
    {
        if (!_writer || !_caseData) return false;
        //create Material adaptor
        if (!_adaptorIO.contains("Material"))
        {
            _adaptorIO.insert("Material", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorMaterial>("BDF", "NastranMaterial"));
        }
        Nastran::FITKNastranAdaptorMaterial* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorMaterial*>(_adaptorIO.value("Material"));
        //check if the Material adaptor is available
        if (adaptor == nullptr) return false;
        //获取管理器
        Interface::FITKMaterialManager * materialMgr = _caseData->getMaterialManager();
        if (!materialMgr) return false;
        //写出材料
        int count = materialMgr->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKAbstractMaterial* materialPtr = materialMgr->getDataByIndex(i);
            if (!materialPtr) continue;
            //Set necessary components for the Material adaptor
            adaptor->setWriter(_writer);
            adaptor->setDataObject(materialPtr);
            bool result = adaptor->adaptW();
            if (!result)
            {
                _writer->consoleMessage(3, QString("write Material err ! %1").arg(materialPtr->getDataObjectName()));
            }
        }
        return true;
    }

    bool FITKNastranAdaptorCase::readProperty()
    {
        if (!_reader || !_caseData) return false;
        //获取管理器
        Interface::FITKAbstractSectionManager * sectionMgr = _caseData->getSectionManager();
        if (!sectionMgr) return false;
        //获取属性数据行
        QString line = _reader->previousLine();
        Interface::FITKAbstractSection* section = nullptr;
        if (line.startsWith("PSHELL"))
            section = new Interface::FITKAbaSectionShellHomogeneous;
        else if (line.startsWith("PBAR"))
            section = new Interface::FITKAbaSectionBeam;
        if (section == nullptr) return false;
        //create Property adaptor
        if (!_adaptorIO.contains("Property"))
        {
            _adaptorIO.insert("Property", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorProperty>("BDF", "NastranProperty"));
        }
        Nastran::FITKNastranAdaptorProperty* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorProperty*>(_adaptorIO.value("Property"));
        //check if the Property adaptor is available
        if (adaptor == nullptr) return false;
        //Set necessary components for the Property adaptor
        adaptor->setReader(_reader);
        adaptor->setDataObject(section);
        bool result = adaptor->adaptR();
        if (!result)
        {
            _reader->consoleMessage(3, QString("read Property err ! %1").arg(line));
            delete section;
            return false;
        }
        //重新设置名称-防止名称重复
        section->setDataObjectName(sectionMgr->checkName(section->getDataObjectName()));
        //添加数据到管理器
        sectionMgr->appendDataObj(section);
        //Return the result of the adaptation process
        return result;
    }

    bool FITKNastranAdaptorCase::writeProperty()
    {
        if (!_writer || !_caseData) return false;
        //create Property adaptor
        if (!_adaptorIO.contains("Property"))
        {
            _adaptorIO.insert("Property", FITKIOADAPTORFACTORY->createT<Nastran::FITKNastranAdaptorProperty>("BDF", "NastranProperty"));
        }
        Nastran::FITKNastranAdaptorProperty* adaptor = dynamic_cast<Nastran::FITKNastranAdaptorProperty*>(_adaptorIO.value("Property"));
        //check if the Property adaptor is available
        if (adaptor == nullptr) return false;
        //获取管理器
        Interface::FITKAbstractSectionManager * sectionMgr = _caseData->getSectionManager();
        if (!sectionMgr) return false;
        //写出属性
        int count = sectionMgr->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKAbstractSection* section = sectionMgr->getDataByIndex(i);
            if (!section) continue;
            //Set necessary components for the Material adaptor
            adaptor->setWriter(_writer);
            adaptor->setDataObject(section);
            bool result = adaptor->adaptW();
            if (!result)
            {
                _writer->consoleMessage(3, QString("write Property err ! %1").arg(section->getDataObjectName()));
            }
        }
        return true;
    }

} // namespace Nastran
